package com.denlaku.longan.util;

import com.denlaku.longan.AppException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * @author tianx
 */
@Slf4j
public class JsonUtil {
    private static final ObjectMapper MAPPER = new ObjectMapper();

    static {
        MAPPER.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, true);
        MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        MAPPER.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        MAPPER.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
    }

    private static final TypeReference<Map<Object, Object>> OBJECT_MAP_REF = new TypeReference<>() {};

    public static <T> String toJsonString(T value) {
        try {
            return MAPPER.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            log.error("toJSONStringError", e);
            throw new AppException(e);
        }
    }

    public static <T> T parseObject(String value, Class<T> cls) {
        try {
            return MAPPER.readValue(value, cls);
        } catch (JsonProcessingException e) {
            log.error("parseJsonByClassError", e);
            throw new AppException(e);
        }
    }

    public static <T> T parseObject(String value, TypeReference<T> typeReference) {
        try {
            return MAPPER.readValue(value, typeReference);
        } catch (JsonProcessingException e) {
            log.error("parseJsonByTypeReferenceError", e);
            throw new AppException(e);
        }
    }

    public static Map<Object, Object> parseObject(String value) {
        try {
            return MAPPER.readValue(value, OBJECT_MAP_REF);
        } catch (JsonProcessingException e) {
            log.error("parseJsonByTypeReferenceError", e);
            throw new AppException(e);
        }
    }
}
